using System;
using System.Collections;
using System.Windows.Forms;
using System.Drawing;
using log4net;
using log4net.Appender;
using log4net.Repository.Hierarchy;
using log4net.Core;
namespace SampleApplication
{
    /// <summary>
    /// Implements a log4net appender to send output to a TextBox control.
    /// </summary>
    public class RichTextBoxAppender : AppenderSkeleton
    {
        #region CONFIG FILE
        //        <appender name="TextBoxAppender" type="MyApp.TextBoxAppender,MyApp">
        //                <threshold value="INFO"/>
        //                <layout type="log4net.Layout.PatternLayout">
        //                                <param name="ConversionPattern" value="%d//%m%n" />
        //                </layout>
        //        </appender>
        #endregion

        private System.Windows.Forms.RichTextBox _richtextBox;

        private delegate void UpdateControlDelegate(LoggingEvent loggingEvent);

        public RichTextBoxAppender()
        {
        }
        private void UpdateControl(LoggingEvent loggingEvent)
        {
            try
            {
                // move selection to EOF if not at EOF
                if (_richtextBox.SelectionStart != _richtextBox.TextLength)
                {
                    _richtextBox.SelectionStart = _richtextBox.TextLength;
                }

                // I looked at the TortoiseCVS code to figure out how
                // to use the RTB as a colored logger.  It noted a performance
                // problem when the buffer got long, so it cleared it every 100K.
                if (_richtextBox.TextLength > 100000)
                {
                    _richtextBox.Clear();
                    _richtextBox.SelectionColor = Color.Gray;
                    _richtextBox.AppendText("(earlier messages cleared because of log length)\n\n");
                }

                switch (loggingEvent.Level.Name)
                {
                    case "INFO":
                        _richtextBox.SelectionColor = System.Drawing.Color.Black;
                        break;
                    case "WARN":
                        _richtextBox.SelectionColor = System.Drawing.Color.Blue;
                        break;
                    case "ERROR":
                        _richtextBox.SelectionColor = System.Drawing.Color.Red;
                        break;
                    case "FATAL":
                        _richtextBox.SelectionColor = System.Drawing.Color.DarkOrange;
                        break;
                    case "DEBUG":
                        _richtextBox.SelectionColor = System.Drawing.Color.DarkGreen;
                        break;
                    default:
                        _richtextBox.SelectionColor = System.Drawing.Color.Black;
                        break;
                }

                _richtextBox.AppendText(loggingEvent.Level.DisplayName + " - " + loggingEvent.MessageObject +"\n");
            }
            catch { }
        }

        protected override void Append(LoggingEvent loggingEvent)
        {
            // prevent Exceptions
            try
            {

                // make thread safe
                if (_richtextBox.InvokeRequired)
                {
                    _richtextBox.Invoke(
                                new UpdateControlDelegate(UpdateControl),
                                new object[] { loggingEvent });
                }
                else
                {
                    UpdateControl(loggingEvent);
                }
            }
            catch
            {
            }

        }
               
        public RichTextBox RichTextBox
        {
                get
                {
                        return _richtextBox;
                }
        }

        public static void SetRichTextBox(ref RichTextBox rtb)
        {
                rtb.ReadOnly = true;
                rtb.HideSelection = false;      // allows rtb toallways append at the end
                rtb.Clear();

                foreach(log4net.Appender.IAppender appender in GetAppenders())
                {
                        if (appender is RichTextBoxAppender)
                        {
                            ((RichTextBoxAppender)appender)._richtextBox = rtb;
                        }
                }
        }

        private static IAppender[] GetAppenders()
        {
                ArrayList appenders = new ArrayList();

                appenders.AddRange(((Hierarchy)LogManager.GetRepository()).Root.Appenders);

                foreach(ILog log in LogManager.GetCurrentLoggers())
                {
                    appenders.AddRange(((Logger)log.Logger).Appenders);
                }

                return  (IAppender[])appenders.ToArray(typeof(IAppender));
        }

    }
}


